package com.wanmait.recycle.service.impl;

import java.io.IOException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wanmait.recycle.dao.SolrDAO;
import com.wanmait.recycle.mapper.ArticleMapper;
import com.wanmait.recycle.pojo.Article;
import com.wanmait.recycle.pojo.CollectArticle;
import com.wanmait.recycle.pojo.PraiseArticle;
import com.wanmait.recycle.pojo.Userinfo;
import com.wanmait.recycle.redis.dao.RedisCollectArticleDao;
import com.wanmait.recycle.redis.dao.RedisPraiseArticleDao;
import com.wanmait.recycle.redis.dao.RedisViewCountDao;
import com.wanmait.recycle.redis.pojo.CollectArticleMessage;
import com.wanmait.recycle.redis.pojo.PraiseArticleMessage;
import com.wanmait.recycle.service.ArticleService;
import com.wanmait.recycle.service.CollectArticleService;
import com.wanmait.recycle.service.ConfigService;
import com.wanmait.recycle.service.PraiseArticleService;
import com.wanmait.recycle.util.PageContext;
import com.wanmait.recycle.util.Pager;
import com.wanmait.recycle.util.RemoveHtmlTagUtil;

@Service
@Transactional
public class ArticleServiceImpl implements ArticleService {

	@Resource
	private ArticleMapper articleMapper;
	@Resource
	private RedisPraiseArticleDao redisPraiseArticleDao;
	@Resource
	private RedisCollectArticleDao redisCollectArticleDao;
	@Resource
	private RedisViewCountDao redisViewCountDao;
	@Resource
	private PraiseArticleService praiseArticleService;
	@Resource
	private CollectArticleService collectArticleService;
	@Resource
	private SolrDAO solrDAO;
	@Resource
	private ConfigService configService;
	
	
	@Override
	public void insert(Article object) {
		// TODO Auto-generated method stub

	}

	@Override
	public void update(Article object) {
		// TODO Auto-generated method stub

	}

	@Override
	public void delete(Integer id) {
		// TODO Auto-generated method stub

	}

	@Override
	public void delete(String ids) {
		// TODO Auto-generated method stub

	}

	@Override
	public Article findById(Integer id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Article> findAll() {
		// TODO Auto-generated method stub
		return articleMapper.findAll();
	}

	@Override
	public int getDataCount() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<Article> findAll(Pager pager) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Article> findAll(Article object) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getDataCount(Article object) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<Article> findAll(Pager pager, Article object) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void shangXian(Integer id) {
		articleMapper.shangXian(id);
		
	}

	@Override
	public void xiaXian(Integer id) {
		articleMapper.xiaXian(id);
		
	}

	@Override
	public void shangXianshangXianByIds(String ids) {
		
		ids = ids.substring(0, ids.length()-1);
		String[] nn =ids.split(",");
		
		articleMapper.shangXianByIds(nn);
		
	}

	@Override
	public void xiaXianByIds(String ids) {
		
		ids = ids.substring(0, ids.length()-1);
		String[] nn =ids.split(",");
		
		articleMapper.xiaXianByIds(nn);
		
	}

	//前台获得enable为1的所有文章 ZQ 03.04
	@Override
	@Cacheable(value="recycle",key="'article'",condition="#pageNum==1")
	public PageInfo<Article> findEnableArticle() {
		Map<String, Map<String,String>> config = configService.findAllConfig();
		PageHelper.startPage(PageContext.getPageNum(), Integer.parseInt(config.get("前台分页").get("webPage")));
		List<Article> articles = articleMapper.findEnableArticle();
		//从redis中获取每篇文章最新的点赞数，放入对象中
		for (Article article : articles) {
			article.setPraiseCount(redisPraiseArticleDao.getCount(article.getId()));
			//从redis中获得收藏数，放入对象中
			article.setCollectCount(redisCollectArticleDao.getCount(article.getId()));
			//从redis中获得浏览数
			article.setViewCount(redisViewCountDao.getArticeViewCount(article.getId()));
		}
		PageInfo<Article> pageInfo = new PageInfo<Article>(articles,7);
		
		return pageInfo;
	}

	/*根据Id查找文章*/
	@Override
	public Article findByArticleId2(Integer id) {
		
		Article article = articleMapper.findByArticleId(id);
	
		return article;
	}
	
	/*根据Id查找文章*/
	@Override
	public Article findByArticleId(Integer id) {
		
		Article article = articleMapper.findByArticleId(id);
		article.setPraiseCount(redisPraiseArticleDao.getCount(id));
		article.setCollectCount(redisCollectArticleDao.getCount(id));
		return article;
	}
	

	/*判断某位用户是否对某个文章点赞*/
	@Override
	public boolean isPraise(Integer articleId, Integer userinfoId) {
		
		return redisPraiseArticleDao.isPraise(articleId, userinfoId);
	}

	/*点赞*/
	@Override
	public void addPraise(Integer articleId, Integer userinfoId) {
		String message;
		redisPraiseArticleDao.addPraiseArticle(articleId, userinfoId);
		//修改总的点赞数量+1
		redisPraiseArticleDao.increaseCount(articleId);
		
		
		message="{\"articleId\":"+articleId+",\"userinfoId\":"+userinfoId+",\"delete\":1,\"inputTime\":"+System.currentTimeMillis()+"}";
		//向队列中添加消息
		redisPraiseArticleDao.leftPush(message);
		//userLike:update:set 哪些问题进行过点赞或者取消点赞
		redisPraiseArticleDao.addUpdate(articleId);
	}

	/*取消点赞*/
	@Override
	public void removePraise(Integer articleId, Integer userinfoId) {
		String message;
		redisPraiseArticleDao.removePraiseArticle(articleId, userinfoId);
		//修改总的点赞数量-1
		redisPraiseArticleDao.decreaseCount(articleId);
		
		message="{\"articleId\":"+articleId+",\"userinfoId\":"+userinfoId+",\"delete\":0,\"inputTime\":"+System.currentTimeMillis()+"}";
		//向队列中添加消息
		redisPraiseArticleDao.leftPush(message);
		//userLike:update:set 哪些问题进行过点赞或者取消点赞
		redisPraiseArticleDao.addUpdate(articleId);
	}
	
	//同步队列
	@Override
	public void processPraiseQueue() {
		//点赞
		List<PraiseArticle> insertPraiseArticleList = new ArrayList<>();
		//取消点赞
		List<PraiseArticle> deletePraiseArticleList = new ArrayList<>();
		
		while(true)
		{
			
			//获取消息，每次二十条
			List<String> messages = this.popPraiseMessage();
			
			for (String message : messages) {
				
				//ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构，反之亦然
				ObjectMapper objectMapper = new ObjectMapper();
				//将redis中的json格式的消息转换为PraiseArticleMessage对象
				PraiseArticleMessage praiseArticleMessage;
				
				try {
					
					praiseArticleMessage = objectMapper.readValue(message, PraiseArticleMessage.class);
					//将解析后的各个属性的值赋给PraiseArtice
					PraiseArticle praiseArticle = new PraiseArticle();
					//存文章id
					Article article = new Article();
					article.setId(praiseArticleMessage.getArticleId());
					praiseArticle.setArticle(article);
					//存用户id
					Userinfo userinfo = new Userinfo();
					userinfo.setId(praiseArticleMessage.getUserinfoId());
					praiseArticle.setUserinfo(userinfo);
					//存加入时间
					praiseArticle.setInputTime(new Timestamp(praiseArticleMessage.getInputTime()));
					//如果isDelete为true，加入点赞。如果为false则加入取消点赞
					if(praiseArticleMessage.isDelete()) {
						
						insertPraiseArticleList.add(praiseArticle);
						
					}else {
						
						deletePraiseArticleList.add(praiseArticle);
					}
					
				} catch (JsonParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (JsonMappingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
			if(insertPraiseArticleList.size()!=0) {
				//批量点赞
				praiseArticleService.insertBatch(insertPraiseArticleList);
			}
			if(deletePraiseArticleList.size()!=0) {
				//批量取消点赞
				praiseArticleService.deleteBatch(deletePraiseArticleList);
			}
			
			//小于20条说明队列中没有消息了
			if(messages.size()<20)
			{
				break;
			}
		}
		
	}
	/*每次从redis中取出20条消息，如果小于20条，则取完*/
	private List<String> popPraiseMessage(){
		
		List<String> messages = new ArrayList<>();
		for (int i = 0; i < 20 ; i++) {
			
			String message = redisPraiseArticleDao.rightPop();
			if(message!=null) {
				messages.add(message);
			}else {
				break;
			}
		}
		return messages;
	}
	

	//同步每篇文章的点赞数
	@Override
	public void processPraiseCount() {
		
		List<Article> articleList = new ArrayList<>();
		Set<Integer> articleIds = redisPraiseArticleDao.getUpdate();
		Article article = null;
		for (Integer articleId : articleIds) {
			article = new Article();
			Integer praiseCount = redisPraiseArticleDao.getCount(articleId);
			article.setId(articleId);
			article.setPraiseCount(praiseCount);
			
			articleList.add(article);
		}
		for (Article article1 : articleList) {
			
			articleMapper.processPraiseCount(article1);
		}
		//redisPraiseArticleDao.removeUpdate();
	}

/*文章收藏*/
	
	/*某用户是否对某文章收藏*/
	@Override
	public boolean isCollect(Integer articleId, Integer userinfoId) {
		
		return redisCollectArticleDao.isCollect(articleId, userinfoId);
	}
	/*添加收藏*/
	@Override
	public void addCollect(Integer articleId, Integer userinfoId) {
		String message;
		//添加收藏
		redisCollectArticleDao.addCollectArticle(articleId, userinfoId);
		//总的收藏数量加1
		redisCollectArticleDao.increaseCount(articleId);
		
		message="{\"articleId\":"+articleId+",\"userinfoId\":"+userinfoId+",\"delete\":1,\"inputTime\":"+System.currentTimeMillis()+"}";
		
		//想队列中添加消息
		redisCollectArticleDao.leftPush(message);
		//有那些文章被操作过
		redisCollectArticleDao.addUpdate(articleId);
		
	}
	/*取消收藏*/
	@Override
	public void removeCollect(Integer articleId, Integer userinfoId) {
		String message;
		//添加收藏
		redisCollectArticleDao.removeCollectArticle(articleId, userinfoId);
		//总的收藏数量减1
		redisCollectArticleDao.decreaseCount(articleId);;
		
		message="{\"articleId\":"+articleId+",\"userinfoId\":"+userinfoId+",\"delete\":0,\"inputTime\":"+System.currentTimeMillis()+"}";
		
		//想队列中添加消息
		redisCollectArticleDao.leftPush(message);
		//有那些文章被操作过
		redisCollectArticleDao.addUpdate(articleId);
	}
	
	/*同步队列*/
	@Override
	public void processCollectQueue() {
		//点赞
		List<CollectArticle> insertCollectArticleList = new ArrayList<>();
		//取消点赞
		List<CollectArticle> deleteCollectArticleList = new ArrayList<>();
		
		while(true)
		{
			
			//获取消息，每次二十条
			List<String> messages = this.popCollectMessage();
			
			for (String message : messages) {
				
				//ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构，反之亦然
				ObjectMapper objectMapper = new ObjectMapper();
				//将redis中的json格式的消息转换为PraiseArticleMessage对象
				CollectArticleMessage collectArticleMessage;
				
				try {
					
					collectArticleMessage = objectMapper.readValue(message, CollectArticleMessage.class);
					//将解析后的各个属性的值赋给PraiseArtice
					CollectArticle collectArticle = new CollectArticle();
					//存文章id
					Article article = new Article();
					article.setId(collectArticleMessage.getArticleId());
					collectArticle.setArticle(article);
					//存用户id
					Userinfo userinfo = new Userinfo();
					userinfo.setId(collectArticleMessage.getUserinfoId());
					collectArticle.setUserinfo(userinfo);
					//存加入时间
					collectArticle.setInputTime(new Timestamp(collectArticleMessage.getInputTime()));
					//如果isDelete为true，加入点赞。如果为false则加入取消点赞
					if(collectArticleMessage.isDelete()) {
						
						insertCollectArticleList.add(collectArticle);
						
					}else {
						
						deleteCollectArticleList.add(collectArticle);
					}
					
				} catch (JsonParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (JsonMappingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
			if(insertCollectArticleList.size()!=0) {
				//批量点赞
				collectArticleService.insertBatch(insertCollectArticleList);
			}
			if(deleteCollectArticleList.size()!=0) {
				//批量取消点赞
				collectArticleService.deleteBatch(deleteCollectArticleList);
			}
			
			//小于20条说明队列中没有消息了
			if(messages.size()<20)
			{
				break;
			}
		}
		
	}

	/*每次从redis中取出20条消息，如果小于20条，则取完*/
	private List<String> popCollectMessage(){
		
		List<String> messages = new ArrayList<>();
		for (int i = 0; i < 20 ; i++) {
			
			String message = redisCollectArticleDao.rightPop();
			if(message!=null) {
				messages.add(message);
			}else {
				break;
			}
		}
		return messages;
	}
	
	/*同步收藏数*/
	@Override
	public void processCollectCount() {
		
		List<Article> articleList = new ArrayList<>();
		Set<Integer> articleIds = redisCollectArticleDao.getUpdate();
		Article article = null;
		for (Integer articleId : articleIds) {
			article = new Article();
			Integer collectCount = redisCollectArticleDao.getCount(articleId);
			article.setId(articleId);
			article.setCollectCount(collectCount);
			
			articleList.add(article);
		}
		for (Article article1 : articleList) {
			
			articleMapper.processCollectCount(article1);
		}
		//redisCollectArticleDao.removeUpdate();
	}
	
	
	
	
	
	/*根据垃圾Id查询文章*/
	@Override
	public PageInfo<Article> findArticleByRubbishId(Integer rubbishId) {
		PageHelper.startPage(PageContext.getPageNum(), 8);
		List<Article> articles = articleMapper.findArticleByRubbishId(rubbishId);
		PageInfo<Article> pageInfo = new PageInfo<Article>(articles,7);
		return pageInfo;
	}

	@Override
	public List<Article> seachBySolr(String keyword, Pager pager) {
		
		pager.setPageSize(5);
		List<Article> articles = solrDAO.findArticlePage(keyword, pager);
		for (Article article : articles) {
			article.setPraiseCount(redisPraiseArticleDao.getCount(article.getId()));
			//从redis中获得收藏数，放入对象中
			article.setCollectCount(redisCollectArticleDao.getCount(article.getId()));
			//从redis中获得浏览数
			article.setViewCount(redisViewCountDao.getArticeViewCount(article.getId()));
		}
		return articles;
	}

	/*根据userinfoId查询文章*/
	@Override
	public PageInfo<Article> findArticleByUserinfoId(Integer userinfoId) {
		Map<String, Map<String,String>> config = configService.findAllConfig();
		PageHelper.startPage(PageContext.getPageNum(),Integer.parseInt(config.get("前台分页").get("webPage")));
		List<Article> articles = articleMapper.findArticleByUserinfoId(userinfoId);
		PageInfo<Article> pageInfo = new PageInfo<Article>(articles,7);
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		//判断文章添加文章后是否超过两个小时，超过两个小时不可修改
		for (Article article : pageInfo.getList()) {
			Timestamp now = new Timestamp(System.currentTimeMillis());
			Timestamp input = article.getInputTime();
			try {
				Long nowTime = sdf.parse(now.toString()).getTime();
				Long inputTime = sdf.parse(input.toString()).getTime();
				if(nowTime-inputTime<2*60*60*1000) {
					article.setTimeout(true);
				}
				
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return pageInfo;
	}


	/*添加文章*/
	@Override
	public void addArticle(Article article) {
		articleMapper.addArticle(article);
		
	}

	
	@Override
	public List<Article> findArticleByRubbishIdpdz(Integer rubbishId) {
		
		List<Article> articles = articleMapper.findArticleByRubbishIdpdz(rubbishId);
		for(Article atc:articles) {
			atc.setContent(RemoveHtmlTagUtil.htmlRemoveTag(atc.getContent()).substring(0,Math.min(120, RemoveHtmlTagUtil.htmlRemoveTag(atc.getContent()).length()-5)));
		}
		return articles;
	}
	
	/*文章评论数加1减1*/
	@Override
	public void updateCommentCount(Integer articleId, Integer count) {
		articleMapper.updateCommentCount(articleId, count);
		
	}

	/*根据用户Id和rubbishId查询文章*/
	@Override
	public PageInfo<Article> findArticleByUserinfoIdAndRubbishId(Integer userinfoId, Integer rubbishId) {
		PageHelper.startPage(PageContext.getPageNum(), 10);
		List<Article> articles = articleMapper.findArticleByUserinfoIdAndRubbishId(userinfoId, rubbishId);
		PageInfo<Article> pageInfo = new PageInfo<>(articles,7);
		return pageInfo;
	}

	/*修改文章*/
	@Override
	public void updateArticle(Article article) {
		
		articleMapper.updateArticle(article);
	}

	/*删除文章*/
	@Override
	public void deleteArticle(Integer articleId) {
		
		articleMapper.deleteArticle(articleId);
	}

	
	/*某篇文章被浏览*/
	@Override
	public void addViewArticle(Integer articleId, String ip) {
		/*添加浏览*/
		redisViewCountDao.addArticleView(articleId, ip);
		/*增加一次浏览次数*/
		redisViewCountDao.increaseArticleViewCount(articleId);
		/*哪些文章被浏览*/
		redisViewCountDao.addUpdateViewArticle(articleId);
	}

	/*判断某篇文章是否被某用户浏览过&&浏览时间是否超过24小时*/
	/*此处返回为是否可以添加浏览，true为可以，false为不可以*/
	@Override
	public boolean isViewArticle(Integer articleId, String ip) {
		
		return redisViewCountDao.isViewArticle(articleId, ip);
	}

	/*同步某文章的浏览次数*/
	@Override
	public void processArticleViewCount() {
		List<Article> articleList = new ArrayList<>();
		Set<Integer> articleIds = redisViewCountDao.getUpdateViewArticle();
		Article article = null;
		for (Integer articleId : articleIds) {
			article = new Article();
			Integer viewCount = redisViewCountDao.getArticeViewCount(articleId);
			article.setId(articleId);
			article.setViewCount(viewCount);;
			
			articleList.add(article);
		}
		for (Article article1 : articleList) {
			
			articleMapper.processArticleViewCount(article1);
		}
		//redisViewCountDao.removeUpdateViewArticle();
		
	}

	@Override
	public PageInfo<Article> findAllByRubbishId(Integer rubbishId) {
		Map<String, Map<String,String>> config = configService.findAllConfig();
		PageHelper.startPage(PageContext.getPageNum(), Integer.parseInt(config.get("前台分页").get("webPage")));
		List<Article> articles = articleMapper.findAllByRubbishId(rubbishId);
		PageInfo<Article> pageInfo = new PageInfo<Article>(articles,7);
		return pageInfo;
	}

	@Override
	public PageInfo<Article> findAllByPageAndRedu() {
		Map<String, Map<String,String>> config = configService.findAllConfig();
		PageHelper.startPage(PageContext.getPageNum(), Integer.parseInt(config.get("前台分页").get("webPage")));
		List<Article> articles = articleMapper.findAllByPageAndRedu();
		PageInfo<Article> pageInfo = new PageInfo<Article>(articles,7);
		return pageInfo;
	}

	@Override
	public PageInfo<Article> findAllByPageAndTime() {
		Map<String, Map<String,String>> config = configService.findAllConfig();
		PageHelper.startPage(PageContext.getPageNum(), Integer.parseInt(config.get("前台分页").get("webPage")));
		List<Article> articles = articleMapper.findAllByPageAndTime();
		PageInfo<Article> pageInfo = new PageInfo<Article>(articles,7);
		return pageInfo;
	}

	/*获得某个用户收藏的所有文章*/
	@Override
	public PageInfo<Article> findCollectArticle(Integer userinfoId) {
		PageHelper.startPage(PageContext.getPageNum(), 10);
		Set<Integer> articleIds = redisCollectArticleDao.getCollectArticleIds(userinfoId);
		List<Article> articles = null;
		if(articleIds.size()!=0) {
			articles = articleMapper.findCollectArticle(articleIds);
			PageInfo<Article> pageInfo = new PageInfo<>(articles,5);
			return pageInfo;
		}

		return null;
	}


	

	
	
	
	
	
	
	
	
	

}
